<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      background-color: lightcyan;
    }
    #tooltip {
      position: absolute;
      z-index: 2;
      background: white;
      padding: 10px;
      border-radius: 2px;
      visibility: hidden;
    }
  </style>
</head>
<body>
  <canvas id="canvas"></canvas>
  <div id="tooltip"></div>
  
  <script src="./js/three.js"></script>
   <script src="./js/OrbitControls.js"></script>
  <script src="./js/d3-geo.v1.min.js"></script> <!-- D3 可视化框架 墨卡托投影转换 -->
  <script>
    class chinaMap {
      constructor () {
        this.init()
      }

      init() {
        // 第一步新建场景
        this.scene = new THREE.Scene()
        this.setCamera()
        this.setRenderer()
        // this.setLight()

        // const geometry = new THREE.BoxGeometry()
        // const material = new THREE.MeshBasicMaterial({color: '#FF0000'})
        // this.cube = new THREE.Mesh(geometry, material)
        // this.scene.add( this.cube )


        this.setController()
        this.setRaycaster()
        this.animate()
        this.loadMapChina()

        // this.render()
        this.addHelper()
      }

      // 设置相机
      setCamera() {
        // 第二个参数是 窗口长度和宽度比
        this.camera = new THREE.PerspectiveCamera(
          75,
          window.innerWidth / window.innerHeight,
          1,
          1000
        )

        // 默认相机和 scene.add() 物体会到 (0,0,0) 坐标
        this.camera.position.z = 5
        this.camera.position.set(0, 120, 120)
        this.camera.lookAt(this.scene.position)

      }

      // 设置渲染器
      setRenderer () {
        this.renderer = new THREE.WebGLRenderer({
          canvas: document.getElementById('canvas'),
          alpha: true
        })
        this.renderer.setClearAlpha(0)
        // 设置画布大小
        this.renderer.setSize(window.innerWidth, window.innerHeight)
        // 这里 其实就是 canvas 画布  renderer.domElement
        console.log(this.renderer.domElement)
        document.body.appendChild(this.renderer.domElement)
      }

      // 设置环境光
      setLight() {
        this.ambientLight = new THREE.AmbientLight(0xffffff) // 环境光
        this.scene.add(this.ambientLight)
      }

      render() {
        this.renderer.render(this.scene, this.camera)
      }

      animate() {
        requestAnimationFrame(this.animate.bind(this))
        this.raycaster.setFromCamera(this.mouse, this.camera)
        console.log(this.raycaster, this.scene.children)
        
        const intersects = this.raycaster.intersectObjects(
          this.scene.children,
          true
        )

        if(this.lastPick) {
          this.lastPick.object.material[0].color.set('#2defff')
          this.lastPick.object.material[1].color.set('#3480C4')
        }
        this.lastPick = null
        this.lastPick = intersects.find(item => item.object.material && item.object.material.length === 2)

        if(this.lastPick) {
          this.lastPick.object.material[0].color.set(0xff0000)
          this.lastPick.object.material[1].color.set(0xff0000)
        }

        this.showTip()
        this.render()
      }

      loadMapChina() {
        const loader = new THREE.FileLoader()
        loader.load('./china.json', (data) => {
          const jsondata = JSON.parse(data)
          this.generateGeometry(jsondata)
        })
      }

      generateGeometry(jsondata) {
        this.map = new THREE.Object3D()

        const projection = d3.geoMercator()
                            .center([104, 37.5])
                            .scale(80)
                            .translate([0, 0])
        jsondata.features.forEach((elem) => {
          const province = new THREE.Object3D()
          province.properties = elem.properties

          const coordinates = elem.geometry.coordinates

          coordinates.forEach((multiPolygon) => {
            multiPolygon.forEach((polygon) => {
              const shape = new THREE.Shape()
              const lineMaterial = new THREE.LineBasicMaterial({color: 'green'})
              const lineGeometry = new THREE.Geometry()

              for(let i = 0; i < polygon.length; i++) {
                const [x, y] = projection(polygon[i])
                if(i === 0) {
                  shape.moveTo(x, -y)
                }
                shape.lineTo(x, -y)
                lineGeometry.vertices.push(new THREE.Vector3(x, -y, 3.01))
              }

              const extrudeSettings = {
                depth: 2,
                bevelEnable: false,
                bevelThickness: 1
              }

              const geometry = new THREE.ExtrudeGeometry(
                shape,
                extrudeSettings
              )
              const material = new THREE.MeshBasicMaterial({
                color: '#2defff',
                transparent: true,
                opacity: 0.6
              })
              const material1 = new THREE.MeshBasicMaterial({
                color: '#3480C4',
                transparent: true,
                opacity: 0.5
              })

              const mesh = new THREE.Mesh(geometry, [material, material1])
              const line = new THREE.Line(lineGeometry, lineMaterial)
              province.add(mesh)
              province.add(line)
            })
          })

          this.map.add(province)
        })
        this.scene.add(this.map)
      }

      showTip() {
        // 显示省份的信息
        if (this.lastPick) {
          const properties = this.lastPick.object.parent.properties

          this.tooltip.textContent = properties.name

          this.tooltip.style.visibility = 'visible'
        } else {
          this.tooltip.style.visibility = 'hidden'
        }
      }
    
      setRaycaster () {
        this.raycaster = new THREE.Raycaster()
        this.mouse = new THREE.Vector2()

        this.tooltip = document.getElementById('tooltip')

        const onMouseMove = (event) => {
          console.log(2222)

          this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1
          this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1

          // 更改div位置
          this.tooltip.style.left = event.clientX + 2 + 'px'
          this.tooltip.style.top = event.clientY + 2 + 'px'

          console.log(this.mouse)

        }

        this.renderer.domElement.addEventListener('mousemove', (event) => {
          console.log(2222)

          this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1
          this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1

          // 更改div位置
          this.tooltip.style.left = event.clientX + 2 + 'px'
          this.tooltip.style.top = event.clientY + 2 + 'px'
          console.log(this.mouse)

        }, false)
        // window.addEventListener('mousedown', (event) => {
          
        //   console.log(1111)
        //   window.addEventListener('mousemove', (event) => {
        //     console.log(33333)
        //   })
        // }, false)

      }
      // 辅助相机
      addHelper() {
        const helper = new THREE.CameraHelper(this.camera)
        this.scene.add(helper)
      }

      setController() {
        this.controller = new THREE.OrbitControls(
          this.camera,
          document.getElementById('canvas')
        )
      }
    }

    let map = new chinaMap()
  </script>
</body>
</html>